/**
 * 
 */
package edu.hit.irlab.coref.evaluation.methds;

import java.util.ArrayList;

import edu.hit.irlab.coref.evaluation.PRScoreStruct;

/**
 * the B_CUBED evaluate algorithm
 * @author chuter
 */
public class Bcubed {
	public static BcubedScore scorePart(
			ArrayList<ArrayList<Integer>> entityMentionsMatchKey,
			ArrayList<ArrayList<Integer>> entityMentionsMatchRes
		) {
		double eneity_total = 0;
		
		for(ArrayList<Integer> oneClusterInStd : entityMentionsMatchKey) 
			eneity_total += oneClusterInStd.size();
	    
	    double precise = 0.0;
	    double recall = 0.0;
	    
	    int stdLen = 0;
	    int resLen = 0;
	    double correct = 0;
	    
	    for(ArrayList<Integer> oneClusterInStd : entityMentionsMatchKey) {
			stdLen = oneClusterInStd.size();
			for(Integer item : oneClusterInStd) {
				for(ArrayList<Integer> oneClusterInRes : entityMentionsMatchRes) {
					if (oneClusterInRes.contains(item)) {
						resLen = oneClusterInRes.size();
						correct = 0;
						for(Integer entity : oneClusterInStd) {
							if (oneClusterInRes.contains(entity)) {
								correct += 1;
							}
						}
						break;
					}
				}

				precise += (correct / resLen);
				recall += (correct / stdLen);
				
			}
		}
	    
	    return new BcubedScore(precise, recall, eneity_total);
	    
	}
	
	public static PRScoreStruct score(
			ArrayList<ArrayList<Integer>> entityMentionsMatchKey,
			ArrayList<ArrayList<Integer>> entityMentionsMatchRes
		) {		
		BcubedScore score = scorePart(entityMentionsMatchKey, entityMentionsMatchRes);
	    double precise = score._precise_part / score.total;
		double recall  = score._recall_part / score.total;
		return new PRScoreStruct(precise, recall);
	}
		
	public static class BcubedScore {
		public double _precise_part;
		public double _recall_part;
		public double total;
		public BcubedScore(double precise, double recall, double total) {
			this._precise_part = precise;
			this._recall_part = recall;
			this.total = total;
		}
		//add two score_parts
		public void add(BcubedScore anotherScore) {
			_precise_part += anotherScore._precise_part;
			_recall_part += anotherScore._recall_part;
			total += anotherScore.total;
		}
		//convert to PRScore
		public PRScoreStruct toPRScore() {
			//P=_precise_part/total, R=_recall_part/total
			return new PRScoreStruct(_precise_part/total, _recall_part/total);
		}
	}
	
	//test
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList<ArrayList<Integer>> standardSet = new ArrayList<ArrayList<Integer>>();
		ArrayList<ArrayList<Integer>> responseSet = new ArrayList<ArrayList<Integer>>();
		ArrayList<ArrayList<Integer>> responseSet2 = new ArrayList<ArrayList<Integer>>();
		ArrayList<Integer> standard1 = new ArrayList<Integer>();
		ArrayList<Integer> standard2 = new ArrayList<Integer>();
		ArrayList<Integer> standard3 = new ArrayList<Integer>();
		ArrayList<Integer> response1 = new ArrayList<Integer>();
		ArrayList<Integer> response2 = new ArrayList<Integer>();
		
		ArrayList<Integer> response12 = new ArrayList<Integer>();
		ArrayList<Integer> response22 = new ArrayList<Integer>();
		
		standard1.add(1);
		standard1.add(2);
		standard1.add(3);
		standard1.add(4);
		standard1.add(5);
		
		standard2.add(6);
		standard2.add(7);
		
		standard3.add(8);
		standard3.add(9);
		standard3.add(10);
		standard3.add(11);
		standard3.add(12);
		
		standardSet.add(standard1);
		standardSet.add(standard2);
		standardSet.add(standard3);
		
		
		response1.add(1);
		response1.add(2);
		response1.add(3);
		response1.add(4);
		response1.add(5);

		response2.add(6);
		response2.add(7);
		
		response2.add(8);
		response2.add(9);
		response2.add(10);
		response2.add(11);
		response2.add(12);
		
		responseSet.add(response1);
		responseSet.add(response2);
		
		response12.add(1);
		response12.add(2);
		response12.add(3);
		response12.add(4);
		response12.add(5);
		response12.add(8);
		response12.add(9);
		response12.add(10);
		response12.add(11);
		response12.add(12);
		
		
		response22.add(6);
		response22.add(7);
		
		responseSet2.add(response12);
		responseSet2.add(response22);
		
		System.out.println(Bcubed.score(standardSet, responseSet));
		
		System.out.println(Bcubed.score(standardSet, responseSet2));
	}
}
